﻿#include "../exercise.h"
#include <algorithm>
#include <string>
#include <vector>

// READ: `std::transform` <https://zh.cppreference.com/w/cpp/algorithm/transform>
// READ: `std::vector::begin` <https://zh.cppreference.com/w/cpp/container/vector/begin>

int main(int argc, char **argv) {
    std::vector<int> val{8, 13, 21, 34, 55};
    // TODO: 调用 `std::transform`，将 `v` 中的每个元素乘以 2，并转换为字符串，存入 `ans`
    // std::vector<std::string> ans

    // 方法1：使用lambda表达式（推荐）
    std::vector<std::string> ans;
    ans.reserve(val.size());  // 预分配空间提高性能

    std::transform(val.begin(), val.end(), std::back_inserter(ans),
        [](int x) { return std::to_string(x * 2); });

    ASSERT(ans.size() == val.size(), "ans size should be equal to val size");
    ASSERT(ans[0] == "16", "ans[0] should be 16");
    ASSERT(ans[1] == "26", "ans[1] should be 26");
    ASSERT(ans[2] == "42", "ans[2] should be 42");
    ASSERT(ans[3] == "68", "ans[3] should be 68");
    ASSERT(ans[4] == "110", "ans[4] should be 110");
    return 0;
}



/*
`std::transform`

`std::vector::begin`



方法思路
理解 std::transform：用于对容器中的每个元素进行转换操作
转换步骤：先将每个元素乘以2，然后转换为字符串
使用lambda表达式：定义转换逻辑






代码解释
1. 核心转换代码
std::transform(val.begin(), val.end(), std::back_inserter(ans),
    [](int x) { return std::to_string(x * 2); });
参数说明：

val.begin(), val.end()：输入范围
std::back_inserter(ans)：输出迭代器，自动插入到ans末尾
[](int x) { return std::to_string(x * 2); }：lambda转换函数
2. Lambda表达式详解
[](int x) { return std::to_string(x * 2); }
[]：捕获列表（空，不捕获任何外部变量）
(int x)：参数列表（接收每个元素）
{ return std::to_string(x * 2); }：函数体（乘以2并转换为字符串）
3. 替代实现方式
预分配空间版本：

std::vector<std::string> ans(val.size());
std::transform(val.begin(), val.end(), ans.begin(),
    [](int x) { return std::to_string(x * 2); });
分步转换版本：

// 先乘以2
std::vector<int> doubled(val.size());
std::transform(val.begin(), val.end(), doubled.begin(),
    std::multiplies<int>());  // 使用函数对象

// 再转换为字符串
std::vector<std::string> ans(doubled.size());
std::transform(doubled.begin(), doubled.end(), ans.begin(),
    [](int x) { return std::to_string(x); });
std::transform 的多种用法
1. 一元变换（当前使用的）
std::transform(input.begin(), input.end(), output.begin(), unary_op);
2. 二元变换
std::transform(input1.begin(), input1.end(), input2.begin(), output.begin(), binary_op);
3. 使用函数指针
std::string doubleToString(int x) {
    return std::to_string(x * 2);
}

std::transform(val.begin(), val.end(), ans.begin(), doubleToString);
4. 使用函数对象
struct Doubler {
    std::string operator()(int x) const {
        return std::to_string(x * 2);
    }
};

std::transform(val.begin(), val.end(), ans.begin(), Doubler());
性能优化建议
1. 预分配空间
ans.reserve(val.size());  // 避免多次重新分配
2. 使用移动语义（C++11以上）
std::transform(val.begin(), val.end(), std::back_inserter(ans),
    [](int x) { return std::to_string(x * 2); });  // 自动使用移动语义
3. 避免不必要的拷贝
// 如果val很大，考虑使用引用捕获
std::transform(val.begin(), val.end(), std::back_inserter(ans),
    [](const auto& x) { return std::to_string(x * 2); });
相关算法对比
算法	用途	特点
std::transform	元素转换	一对一映射
std::for_each	遍历操作	无返回值
std::generate	生成元素	使用生成器函数
std::copy	复制元素	直接复制，无转换
实际应用场景
1. 数据清洗
// 将所有负数转换为正数
std::transform(data.begin(), data.end(), data.begin(),
    [](int x) { return std::abs(x); });
2. 单位转换
// 英里转换为公里
std::transform(miles.begin(), miles.end(), kilometers.begin(),
    [](double m) { return m * 1.60934; });
3. 对象属性提取
struct Person { std::string name; int age; };
std::vector<Person> people;

// 提取所有人的名字
std::vector<std::string> names;
std::transform(people.begin(), people.end(), std::back_inserter(names),
    [](const Person& p) { return p.name; });
测试验证
程序运行后会通过所有测试：

ans 大小与 val 相同
每个元素正确转换为原来的2倍
转换结果为字符串格式
这个练习展示了 std::transform 的强大功能，它是STL算法中非常实用的工具，可以简洁高效地处理容器元素的转换操作。
*/
